package com.example.demo.use_demo.a_shiro;

import com.example.demo.use_demo.a_shiro.entity.Account;
import com.example.demo.use_demo.a_shiro.entity.Role;
import com.example.demo.use_demo.a_shiro.service.IAccountService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

/**
 * @author zhangqiang
 * @version 1.0
 * @date 2025/02/08
 */
public class AccountRealm extends AuthorizingRealm {

    @Autowired
    private IAccountService accountService;

    /**
     * 执行步骤：
     * 1.Controller登录 -> 2.doGetAuthenticationInfo -> 3.doGetAuthorizationInfo
     */

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取当前登录用户信息
        Subject subject = SecurityUtils.getSubject();
        Account account = (Account) subject.getPrincipal();

        // 设置角色
        Set<String> roles = new HashSet<>();
        roles.add(account.getRole().getRole());
        SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo(roles);

        // 设置权限
        Set<String> perms = new HashSet<>();
        perms.add(account.getRole().getPerms());
        simpleAuthenticationInfo.addStringPermissions(perms);

        return simpleAuthenticationInfo;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 客户输入的用户名和密码会自动封装到对象AuthenticationToken
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        Account foundAccount = accountService.findByUsername(token.getUsername());

        // SimpleAuthenticationInfo会自动验证token中的密码与数据库密码
        if(foundAccount != null){
            return new SimpleAuthenticationInfo(foundAccount,foundAccount.getPassword(),getName());
        }
        return null;
    }
}
